package gui;

import gui.event.Collision;
import gui.event.GameController;
import gui.event.HexGrid;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import dal.object.*;

import core.Physics;

import dal.MapStruct;

/**
 * Class for */
public class PlayersMap extends LayeredPane{
	private static final long serialVersionUID = 1L;
	private static Physics physics;
	private Robot robot;
	private HexGrid hg;
	private Collision cld;
	private MapStruct ms;
	public static int xBall, yBall;
	public static Ball ball;
	
	/**
	 * Constructor for class.
	 * @param ms is for storing and forwarding the informations from the map.
	 * @param tools 
	 * */
	public PlayersMap(MapStruct ms, ToolContainer tools){
		super(ms);
		physics = new Physics(this);
		hg = new HexGrid(ms);
		cld = new Collision(ms, this, tools);
		new GameController(this, tools);
		
		this.ms = ms;
		try {
			robot = new Robot();
		} catch (AWTException e1) {
			e1.printStackTrace();
		}
		
		//getLayers().getComponentsInLayer(3)
		addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseMoved(MouseEvent e) {
				int energyX = e.getXOnScreen() - MainWindow.getCenterX();
				int energyY = e.getYOnScreen() - MainWindow.getCenterY();
				if( (energyX != 0) || (energyY != 0) ){
					physics.energyPassing(energyX << 12, energyY << 12);
					robot.mouseMove(MainWindow.getCenterX(), MainWindow.getCenterY());
					super.mouseMoved(e);
				}
			}
		});		
		
		MainWindow.getMainWindow().setCenter();
		robot.mouseMove(MainWindow.getCenterX(), MainWindow.getCenterY());		
		ball = this.ballDrawer.ball;
		this.setCursor(GameConstants.INVISIBLE_CURSOR);
	}
	
	public static Physics getPhysics(){
		return physics;
	}
	
	/**
	 * Returns with the ball's mass.
	 * @return: the ball's mass
	 * */
	public int getBallMass(){
		return 60;
	}
	
	/**
	 * Calculates the current manoeuvrablility of the ball.
	 * @return: the manoeuvrablility of the ball over the position on which it is.
	 * */
	public double getManoeuvrability(){
		int index = hg.convertToIndex( (int) ballDrawer.x + Ball.getOx(), (int) ballDrawer.y + Ball.getOy()); 
		
		if ( index >= 0){
			return ((Ground) ms.getGroundsVector().get(index)).getManoeuvrability();
		} else {
			return 1;
		}
	}
	
	/**
	 * Calculates the friction coefficient.
	 * @return: the coefficient of the ground on which is the ball.
	 * */
	public double getFrictionalCoefficient(){
		xBall = (int) ballDrawer.x + Ball.getOx();
		yBall = (int) ballDrawer.y + Ball.getOy();
		
		int index = hg.convertToIndex(xBall, yBall); 
		
		if ( index >= 0 ) {
			Ground ground = (Ground) ms.getGroundsVector().get(index);
			GameController.sinking(ground);
			
			return ground.getFrictionCoefficient();
		} else {
			GameController.gameOver();

			return 500;
		}
	}
	
	/**
	 * Moves the ball by (vx, vy)
	 * @param vx is the distance on x axis
	 * @param vy is the distance on y axis
	 * @param energyY 
	 * @param energyX 
	 * @return 
	 * */
	public boolean moveBall(double dx, double dy, double vx, double vy){
		boolean collision = cld.collisionDetected((hg.getVerticalIndex() & 1) == 1, hg.getIndex(), 
				ballDrawer.getBallOrigoX() + dx, ballDrawer.getBallOrigoY() + dy, vx, vy);
		
		if(!collision){
			ballDrawer.moveBall(dx, dy);
		}
		
		return collision;
	}
}
